home *** CD-ROM | disk | FTP | other *** search
/ Amiga Plus 2002 #3 / Amiga Plus CD - 2002 - No. 03.iso / AmiSoft / Util / Misc / Reportplus.lha / reportplus / source / f8.c < prev    next >
C/C++ Source or Header  |  2003-02-14  |  60KB  |  1,700 lines

  1. #include <exec/types.h>
  2. #include <exec/memory.h>
  3. #include <proto/exec.h>
  4. #include <intuition/intuition.h>
  5. #include <intuition/gadgetclass.h>
  6. #include <proto/intuition.h>
  7. #include <libraries/gadtools.h>
  8. #include <proto/gadtools.h>
  9. #include <dos/dos.h>
  10. #include <dos/exall.h>
  11. #include <dos/dostags.h>
  12. #include <proto/dos.h>
  13. #include <graphics/gfx.h>
  14. #include <clib/graphics_protos.h>
  15. #include <clib/alib_protos.h>
  16. #include <libraries/asl.h>
  17. #include <clib/asl_protos.h>
  18.  
  19. #include <ctype.h>
  20. #include <stdlib.h>
  21. #include <string.h>
  22. #include "rp.h"
  23.  
  24. #define ALL_REACTION_CLASSES
  25. #include <reaction/reaction.h>
  26.  
  27. #define TRUNCATE            39
  28. #define GRANULARITY_DIRS    10
  29. #define GRANULARITY_FILES   10
  30.  
  31. MODULE void parent(void);
  32. MODULE void root(void);
  33. MODULE void pathasl(void);
  34. MODULE void writeline(void);
  35. MODULE void killsizelist(void);
  36. MODULE void ghost(void);
  37. MODULE void unghost(void);
  38. MODULE void scale(ULONG bytes);
  39. // MODULE void __inline progressbar(ULONG level);
  40. MODULE void examine(STRPTR thename, ULONG nesting, ULONG parentdir);
  41. MODULE void AddSpecialNode(struct List* ListPtr, STRPTR pathname, ULONG nesting, ULONG unslacksize, ULONG slacksize, ULONG parentdir, ULONG key, LONG type, LONG prot);
  42. MODULE void FreeSpecialNodes(struct List* ListPtr);
  43. MODULE void print_node(ULONG passedkey);
  44. MODULE void print_entry(struct SpecialNode* NodePtr);
  45. MODULE void print_list(ABOOL close);
  46. MODULE void busy(void);
  47.  
  48. #define UNITOPTIONS 3 // counting from 0
  49. MODULE STRPTR UnitOptions[UNITOPTIONS + 1] =
  50. {   "Bytes",
  51.     "Kilobytes",
  52.     "Megabytes",
  53.     "Blocks"
  54. };
  55.  
  56. MODULE struct SpecialNode
  57. {   struct Node Node;
  58.     ULONG       nesting,
  59.                 unslacksize,
  60.                 slacksize,
  61.                 parentdir,
  62.                 key;
  63.     LONG        type,
  64.                 prot;
  65.     TEXT        pathname[1];
  66. };
  67.  
  68. MODULE struct ColumnInfo SizeColumnInfo[] =
  69. { { 75,            // WORD   ci_Width
  70.     "Pathname",    // STRPTR ci_Title
  71.     0,             // ULONG  ci_Flags
  72.   },
  73.   { 25,
  74.     "Size",
  75.     0, /* Last column must not have CIF_DRAGGABLE set (CIF_DRAGGABLE applies
  76.           to the right border of the relevant column). */
  77.   },
  78.   { -1, (STRPTR) ~0, -1
  79. } };
  80.  
  81. IMPORT struct TextAttr     Topaz8;
  82. IMPORT SBYTE               page;
  83. IMPORT TEXT                weekdaystring[LEN_DATSTRING],
  84.                            datestring[LEN_DATSTRING],
  85.                            timestring[LEN_DATSTRING],
  86.                            asldir[PATHNAMEFIELD + 1],
  87.                            aslresult[PATHNAMEFIELD + 1],
  88.                            IOBuffer[LONGESTFIELD + 1];
  89. IMPORT struct SharedStruct shared;
  90. IMPORT struct Screen*      ScreenPtr;
  91. IMPORT struct Window*      MainWindowPtr;
  92. IMPORT struct ExAllData*   EADataPtr;
  93. IMPORT struct Menu*        MenuPtr;
  94. IMPORT Object*             WinObject[FUNCTIONS + 1];
  95. IMPORT ULONG               increment;
  96.  
  97. AGLOBAL struct Gadget*     size_gadgets[GIDS_8 + 1];
  98. AGLOBAL struct SizeStruct  size =
  99. {   0, 0, 0, 0, 0, 0, 0, 0,
  100.     (ULONG) FALSE, (ULONG) FALSE, (ULONG) FALSE,
  101.     "RAM:", "RAM:", "RAM:ReportPlus.log"
  102. };
  103.  
  104. MODULE struct List         SizeList,
  105.                            EmptySizeList,
  106.                            List1,
  107.                            List2;
  108. MODULE BPTR                DirHandle      = NULL,
  109.                            LogFileHandle  = NULL;
  110. MODULE TEXT                logstring[1024 + 1];
  111. MODULE UBYTE               commastring[13 + 1];
  112. MODULE ULONG               status         = STATUS_READY,
  113.                            key            = 0,
  114.                            topnesting     = 0,
  115.                            showall        = TRUE,
  116.                            showfiles      = TRUE;
  117.  
  118. AGLOBAL void size_init(void)
  119. {   struct ListBrowserNode* ListBrowserNodePtr;
  120.  
  121.     NewList(&List1);
  122.     NewList(&List2);
  123.     NewList(&SizeList);
  124.  
  125.     /* Create a 2-column listbrowser list with only one node containing
  126.     only column tags. */
  127.     NewList(&EmptySizeList);
  128.     if (!(ListBrowserNodePtr = AllocListBrowserNode
  129.     (   2,                  // columns
  130.         /* LBNCA_ tags are those that apply to the specific column. */
  131.         LBNA_Column,        0,
  132.         LBNA_Column,        1,
  133.         TAG_END
  134.     )))
  135.     {   rq("Can't create ReAction listbrowser.gadget node(s)!");
  136.     }
  137.     AddTail(&EmptySizeList, (struct Node *) ListBrowserNodePtr); // AddTail() has no return code
  138. }
  139.  
  140. AGLOBAL void size1(void)
  141. {   struct Hook         Hook8Struct;
  142.     struct List         ChooserList;
  143.     struct ChooserNode* ChooserNodePtr[UNITOPTIONS + 1];
  144.     ULONG               i;
  145.  
  146.     NewList(&ChooserList);
  147.     for (i = 0; i <= UNITOPTIONS; i++)
  148.     {   if (!(ChooserNodePtr[i] = (struct ChooserNode *) AllocChooserNode(CNA_Text, UnitOptions[i], TAG_DONE)))
  149.         {   rq("Can't allocate chooser node!");
  150.         }
  151.         AddTail(&ChooserList, (struct Node *) ChooserNodePtr[i]);
  152.     } // automatically freed by ReAction at DisposeObject() time
  153.  
  154.     InitHook(&Hook8Struct, Hook8Func, NULL);
  155.  
  156.     /* Create the window object. */
  157.     lockscreen();
  158.  
  159.     /* We can't just use EmptyList for an empty columnar list, we
  160.     actually need a node (with the LBNA_Column tags) to be present.
  161.  
  162.     LISTBROWSER_ScrollRaster seems not to be usable with
  163.     multi-column lists. */
  164.  
  165.     if (!(WinObject[8] =          NewObject(WINDOW_GetClass(), NULL,
  166.     // window
  167.     WA_PubScreen,                 ScreenPtr,
  168.     WA_ScreenTitle,               "Report+",
  169.     WA_Title,                     "Report+: Path Size Report",
  170.     WA_Activate,                  TRUE,
  171.     WA_DepthGadget,               TRUE,
  172.     WA_DragBar,                   TRUE,
  173.     WA_CloseGadget,               TRUE,
  174.     WA_SizeGadget,                TRUE,
  175.     WA_IDCMP,                     IDCMP_RAWKEY,
  176.     WINDOW_IDCMPHook,             &Hook8Struct,
  177.     WINDOW_IDCMPHookBits,         IDCMP_RAWKEY,
  178.     WINDOW_MenuStrip,             MenuPtr,
  179.     WINDOW_Position,              WPOS_CENTERSCREEN,
  180.     WINDOW_ParentGroup,           size_gadgets[GID_8_LY1] =
  181.     NewObject
  182.     (       LAYOUT_GetClass(), NULL,
  183.             // root-layout
  184.             LAYOUT_Orientation,        LAYOUT_ORIENT_VERT,
  185.             LAYOUT_SpaceOuter,         TRUE,
  186.             LAYOUT_DeferLayout,        TRUE,
  187.             LAYOUT_AddChild,
  188.             NewObject
  189.             (   LAYOUT_GetClass(),     NULL,
  190.                 LAYOUT_Orientation,    LAYOUT_ORIENT_HORIZ,
  191.                 LAYOUT_VertAlignment,  LALIGN_CENTER,
  192.                 LAYOUT_HorizAlignment, LALIGN_CENTER,
  193.                 LAYOUT_BevelStyle,     BVS_NONE,
  194.                 LAYOUT_AddImage,
  195.                 NewObject
  196.                 (   LABEL_GetClass(),  NULL,
  197.                     LABEL_Text,        "_Path:",
  198.                     LABEL_Justification,LJ_LEFT,
  199.                 TAG_END),
  200.                 CHILD_WeightedWidth,   0,
  201.                 LAYOUT_AddChild,       size_gadgets[GID_8_ST1] =
  202.                 NewObject
  203.                 (   STRING_GetClass(), NULL,
  204.                     GA_ID,             GID_8_ST1,
  205.                     GA_RelVerify,      TRUE,
  206.                     GA_TabCycle,       TRUE,
  207.                     STRINGA_TextVal,   size.path,
  208.                     STRINGA_MinVisible,20,
  209.                 TAG_END),
  210.                 LAYOUT_AddChild,       size_gadgets[GID_8_BU1] =
  211.                 NewObject(NULL,        "button.gadget",
  212.                     GA_ID,             GID_8_BU1,
  213.                     GA_RelVerify,      TRUE,
  214.                     BUTTON_AutoButton, BAG_POPFILE,
  215.                 TAG_END),
  216.                 CHILD_WeightedWidth,   0,
  217.             TAG_END),
  218.             CHILD_WeightedHeight,      0,
  219.             LAYOUT_AddChild,           NewObject(LAYOUT_GetClass(), NULL,
  220.                 LAYOUT_Orientation,    LAYOUT_ORIENT_HORIZ,
  221.                 LAYOUT_VertAlignment,  LALIGN_CENTER,
  222.                 LAYOUT_HorizAlignment, LALIGN_CENTER,
  223.                 LAYOUT_BevelStyle,     BVS_NONE,
  224.                 LAYOUT_ShrinkWrap,     TRUE,
  225.                 LAYOUT_AddChild,       size_gadgets[GID_8_CB1] =
  226.                 NewObject
  227.                 (   CHECKBOX_GetClass(),NULL,
  228.                     // checkbox
  229.                     GA_ID,             GID_8_CB1,
  230.                     GA_RelVerify,      TRUE,
  231.                     GA_Text,           "_Log to:",
  232.                     GA_Selected,       (BOOL) size.log,
  233.                     TAG_END
  234.                 ),
  235.                 CHILD_WeightedWidth,   0,
  236.                 LAYOUT_AddChild,       size_gadgets[GID_8_ST2] =
  237.                                        NewObject(STRING_GetClass(), NULL,
  238.                     // string        
  239.                     GA_ID,             GID_8_ST2,
  240.                     GA_RelVerify,      TRUE,
  241.                     GA_TabCycle,       TRUE,
  242.                     STRINGA_TextVal,   size.logfile,
  243.                     STRINGA_MinVisible,20,
  244.                     GA_Disabled,       !size.log,
  245.                     TAG_END
  246.                 ),
  247.                 LAYOUT_AddChild,       size_gadgets[GID_8_BU3] =
  248.                 NewObject
  249.                 (   NULL,              "button.gadget",
  250.                     // button
  251.                     GA_ID,             GID_8_BU3,
  252.                     GA_RelVerify,      TRUE,
  253.                     BUTTON_AutoButton, BAG_POPFILE,
  254.                     GA_Disabled,       !size.log,
  255.                     TAG_END
  256.                 ),
  257.                 CHILD_WeightedWidth,   0,
  258.                 TAG_END
  259.             ),
  260.             CHILD_WeightedHeight,      0,
  261.             LAYOUT_AddChild,
  262.             NewObject
  263.             (   LAYOUT_GetClass(),     NULL,
  264.                 LAYOUT_Orientation,    LAYOUT_ORIENT_VERT,
  265.                 LAYOUT_SpaceOuter,     TRUE,
  266.                 LAYOUT_VertAlignment,  LALIGN_CENTER,
  267.                 LAYOUT_HorizAlignment, LALIGN_CENTER,
  268.                 LAYOUT_BevelStyle,     BVS_FIELD,
  269.                 LAYOUT_AddChild,
  270.                 NewObject
  271.                 (   LAYOUT_GetClass(),     NULL,
  272.                     LAYOUT_Orientation,    LAYOUT_ORIENT_HORIZ,
  273.                     LAYOUT_VertAlignment,  LALIGN_CENTER,
  274.                     LAYOUT_HorizAlignment, LALIGN_CENTER,
  275.                     LAYOUT_BevelStyle,     BVS_NONE,
  276.                     LAYOUT_AddChild,       size_gadgets[GID_8_BU6] =
  277.                     NewObject
  278.                     (   NULL,              "button.gadget",
  279.                         GA_ID,             GID_8_BU6,
  280.                         GA_RelVerify,      TRUE,
  281.                         GA_Text,           "_Root",
  282.                         TAG_END
  283.                     ),
  284.                     CHILD_WeightedWidth,   50,
  285.                     LAYOUT_AddChild,       size_gadgets[GID_8_BU7] =
  286.                     NewObject             
  287.                     (   NULL,              "button.gadget",
  288.                         GA_ID,             GID_8_BU7,
  289.                         GA_RelVerify,      TRUE,
  290.                         GA_Text,           "P_arent",
  291.                         TAG_END
  292.                     ),
  293.                     CHILD_WeightedWidth,   50,
  294.                 TAG_END),
  295.                 CHILD_WeightedHeight,      0,
  296.                 LAYOUT_AddChild,           size_gadgets[GID_8_LB2] =
  297.                 NewObject
  298.                 (   LISTBROWSER_GetClass(),NULL,
  299.                     GA_ID,                 GID_8_LB2,
  300.                     GA_RelVerify,          TRUE,
  301.                     GA_TextAttr,           &Topaz8,
  302.                     LISTBROWSER_Labels,    (ULONG) &EmptySizeList,
  303.                     LISTBROWSER_ColumnInfo,(ULONG) &SizeColumnInfo,
  304.                     LISTBROWSER_ColumnTitles,TRUE,
  305.                     LISTBROWSER_MinVisible,6,
  306.                 TAG_END),
  307.                 CHILD_WeightedHeight,      100,
  308.                 CHILD_MinHeight,           160,
  309.                 LAYOUT_AddChild,
  310.                 NewObject
  311.                 (   LAYOUT_GetClass(),     NULL,
  312.                     LAYOUT_Orientation,    LAYOUT_ORIENT_HORIZ,
  313.                     LAYOUT_VertAlignment,  LALIGN_LEFT,
  314.                     LAYOUT_HorizAlignment, LALIGN_RIGHT,
  315.                     LAYOUT_BevelStyle,     BVS_NONE,
  316.                     LAYOUT_AddChild,
  317.                     NewObject
  318.                     (   LAYOUT_GetClass(),     NULL,
  319.                         LAYOUT_Orientation,    LAYOUT_ORIENT_VERT,
  320.                         LAYOUT_VertAlignment,  LALIGN_CENTER,
  321.                         LAYOUT_HorizAlignment, LALIGN_RIGHT,
  322.                         LAYOUT_BevelStyle,     BVS_NONE,
  323.                         LAYOUT_AddImage,
  324.                         NewObject
  325.                         (   LABEL_GetClass(),  NULL,
  326.                             LABEL_Text,        "Files:",
  327.                             LABEL_Justification,LJ_CENTRE,
  328.                         TAG_END),
  329.                         CHILD_WeightedHeight,  0,
  330.                         LAYOUT_AddImage,
  331.                         NewObject
  332.                         (   LABEL_GetClass(),  NULL,
  333.                             LABEL_Text,        "Directories:",
  334.                             LABEL_Justification,LJ_CENTRE,
  335.                         TAG_END),
  336.                         CHILD_WeightedHeight,  0,
  337.                         LAYOUT_AddImage,
  338.                         NewObject
  339.                         (   LABEL_GetClass(),  NULL,
  340.                             LABEL_Text,        "Block size:",
  341.                             LABEL_Justification,LJ_CENTRE,
  342.                         TAG_END),
  343.                         CHILD_WeightedHeight,  0,
  344.                     TAG_END),
  345.                     CHILD_WeightedWidth,       0,
  346.                     LAYOUT_AddChild,
  347.                     NewObject
  348.                     (   LAYOUT_GetClass(),     NULL,
  349.                         LAYOUT_Orientation,    LAYOUT_ORIENT_VERT,
  350.                         LAYOUT_VertAlignment,  LALIGN_CENTER,
  351.                         LAYOUT_HorizAlignment, LALIGN_RIGHT,
  352.                         LAYOUT_BevelStyle,     BVS_NONE,
  353.                         LAYOUT_AddChild,       size_gadgets[GID_8_ST6] =
  354.                         NewObject
  355.                         (   STRING_GetClass(), NULL,
  356.                             GA_ID,             GID_8_ST6,
  357.                             GA_ReadOnly,       TRUE,
  358.                             STRINGA_TextVal,   "-",
  359.                             STRINGA_MinVisible,13,
  360.                             STRINGA_Justification,GACT_STRINGRIGHT,
  361.                             GA_TextAttr,       &Topaz8,
  362.                         TAG_END),
  363.                         CHILD_WeightedHeight,  0,
  364.                         LAYOUT_AddChild,       size_gadgets[GID_8_ST7] =
  365.                         NewObject
  366.                         (   STRING_GetClass(), NULL,
  367.                             GA_ID,             GID_8_ST7,
  368.                             GA_ReadOnly,       TRUE,
  369.                             STRINGA_TextVal,   "-",
  370.                             STRINGA_MinVisible,13,
  371.                             STRINGA_Justification,GACT_STRINGRIGHT,
  372.                             GA_TextAttr,       &Topaz8,
  373.                         TAG_END),
  374.                         CHILD_WeightedHeight,  0,
  375.                         LAYOUT_AddChild,       size_gadgets[GID_8_ST8] =
  376.                         NewObject
  377.                         (   STRING_GetClass(), NULL,
  378.                             GA_ID,             GID_8_ST8,
  379.                             GA_ReadOnly,       TRUE,
  380.                             STRINGA_TextVal,   "-",
  381.                             STRINGA_MinVisible,13,
  382.                             STRINGA_Justification,GACT_STRINGRIGHT,
  383.                             GA_TextAttr,       &Topaz8,
  384.                         TAG_END),
  385.                         CHILD_WeightedHeight,  0,
  386.                     TAG_END),
  387.                     CHILD_WeightedWidth,       0,
  388.                     LAYOUT_AddImage,           NewObject
  389.                     (   LABEL_GetClass(),      NULL,
  390.                         LABEL_Text,            "",
  391.                         TAG_END
  392.                     ),
  393.                     CHILD_WeightedWidth,       100,
  394.                     LAYOUT_AddChild,
  395.                     NewObject
  396.                     (   LAYOUT_GetClass(),     NULL,
  397.                         LAYOUT_Orientation,    LAYOUT_ORIENT_VERT,
  398.                         LAYOUT_VertAlignment,  LALIGN_CENTER,
  399.                         LAYOUT_HorizAlignment, LALIGN_RIGHT,
  400.                         LAYOUT_BevelStyle,     BVS_NONE,
  401.                         LAYOUT_AddImage,
  402.                         NewObject
  403.                         (   LABEL_GetClass(),  NULL,
  404.                             LABEL_Text,        "Used in path:",
  405.                             LABEL_Justification,LJ_RIGHT,
  406.                         TAG_END),
  407.                         CHILD_WeightedHeight,  0,
  408.                         LAYOUT_AddImage,
  409.                         NewObject
  410.                         (   LABEL_GetClass(),  NULL,
  411.                             LABEL_Text,        "Free on volume:",
  412.                             LABEL_Justification,LJ_RIGHT,
  413.                         TAG_END),
  414.                         CHILD_WeightedHeight,  0,
  415.                         LAYOUT_AddImage,
  416.                         NewObject
  417.                         (   LABEL_GetClass(),  NULL,
  418.                             LABEL_Text,        "Volume capacity:",
  419.                             LABEL_Justification,LJ_RIGHT,
  420.                         TAG_END),
  421.                         CHILD_WeightedHeight,  0,
  422.                     TAG_END),
  423.                     CHILD_WeightedWidth,       0,
  424.                     LAYOUT_AddChild,
  425.                     NewObject
  426.                     (   LAYOUT_GetClass(),     NULL,
  427.                         LAYOUT_Orientation,    LAYOUT_ORIENT_VERT,
  428.                         LAYOUT_VertAlignment,  LALIGN_CENTER,
  429.                         LAYOUT_HorizAlignment, LALIGN_RIGHT,
  430.                         LAYOUT_BevelStyle,     BVS_NONE,
  431.                         LAYOUT_AddChild,       size_gadgets[GID_8_ST4] =
  432.                         NewObject
  433.                         (   STRING_GetClass(), NULL,
  434.                             GA_ID,             GID_8_ST4,
  435.                             GA_ReadOnly,       TRUE,
  436.                             STRINGA_TextVal,   "-",
  437.                             STRINGA_MinVisible,13,
  438.                             STRINGA_Justification,GACT_STRINGRIGHT,
  439.                             GA_TextAttr,       &Topaz8,
  440.                         TAG_END),
  441.                         CHILD_WeightedHeight,  0,
  442.                         LAYOUT_AddChild,       size_gadgets[GID_8_ST5] =
  443.                         NewObject
  444.                         (   STRING_GetClass(), NULL,
  445.                             GA_ID,             GID_8_ST5,
  446.                             GA_ReadOnly,       TRUE,
  447.                             STRINGA_TextVal,   "-",
  448.                             STRINGA_MinVisible,13,
  449.                             STRINGA_Justification,GACT_STRINGRIGHT,
  450.                             GA_TextAttr,       &Topaz8,
  451.                         TAG_END),
  452.                         CHILD_WeightedHeight,  0,
  453.                         LAYOUT_AddChild,       size_gadgets[GID_8_ST3] =
  454.                         NewObject
  455.                         (   STRING_GetClass(), NULL,
  456.                             GA_ID,             GID_8_ST3,
  457.                             GA_ReadOnly,       TRUE,
  458.                             STRINGA_TextVal,   "-",
  459.                             STRINGA_MinVisible,13,
  460.                             STRINGA_Justification,GACT_STRINGRIGHT,
  461.                             GA_TextAttr,       &Topaz8,
  462.                         TAG_END),
  463.                         CHILD_WeightedHeight,  0,
  464.                     TAG_END),
  465.                     CHILD_WeightedWidth,       0,
  466.                 TAG_END),
  467.                 CHILD_WeightedHeight,          0,
  468.             TAG_END),
  469.             CHILD_WeightedHeight,              70,
  470.             LAYOUT_AddChild,
  471.             NewObject
  472.             (   LAYOUT_GetClass(),     NULL,
  473.                 LAYOUT_Orientation,    LAYOUT_ORIENT_HORIZ,
  474.                 LAYOUT_VertAlignment,  LALIGN_CENTER,
  475.                 LAYOUT_HorizAlignment, LALIGN_CENTER,
  476.                 LAYOUT_BevelStyle,     BVS_NONE,
  477.                 LAYOUT_AddChild,       size_gadgets[GID_8_CB4] =
  478.                 NewObject
  479.                 (   CHECKBOX_GetClass(),NULL,
  480.                     // checkbox
  481.                     GA_ID,             GID_8_CB4,
  482.                     GA_RelVerify,      TRUE,
  483.                     GA_Text,           "Show s_ubdirectories?",
  484.                     GA_Selected,       (BOOL) showall,
  485.                 TAG_END),
  486.                 CHILD_WeightedWidth,   0,
  487.                 LAYOUT_AddChild,       size_gadgets[GID_8_CB5] =
  488.                 NewObject
  489.                 (   CHECKBOX_GetClass(),NULL,
  490.                     // checkbox
  491.                     GA_ID,             GID_8_CB5,
  492.                     GA_RelVerify,      TRUE,
  493.                     GA_Text,           "Show _files?",
  494.                     GA_Selected,       (BOOL) showfiles,
  495.                 TAG_END),
  496.                 CHILD_WeightedWidth,   0,
  497.                 LAYOUT_AddImage,       NewObject
  498.                 (   LABEL_GetClass(),  NULL,
  499.                     LABEL_Text,        "",
  500.                     TAG_END
  501.                 ),
  502.                 CHILD_WeightedWidth,   100,
  503.             TAG_END),
  504.             CHILD_WeightedHeight,      0,
  505.             LAYOUT_AddChild,
  506.             NewObject
  507.             (   LAYOUT_GetClass(),     NULL,
  508.                 LAYOUT_Orientation,    LAYOUT_ORIENT_HORIZ,
  509.                 LAYOUT_VertAlignment,  LALIGN_CENTER,
  510.                 LAYOUT_HorizAlignment, LALIGN_CENTER,
  511.                 LAYOUT_BevelStyle,     BVS_NONE,
  512.                 LAYOUT_AddImage,
  513.                 NewObject
  514.                 (   LABEL_GetClass(),  NULL,
  515.                     // label
  516.                     LABEL_Text,        "_View as:",
  517.                     LABEL_Justification,LJ_RIGHT,
  518.                 TAG_END),
  519.                 CHILD_WeightedWidth,   0,
  520.                 LAYOUT_AddChild,       size_gadgets[GID_8_CH1] =
  521.                 NewObject
  522.                 (   CHOOSER_GetClass(),NULL,
  523.                     GA_ID,             GID_8_CH1,
  524.                     GA_RelVerify,      TRUE,
  525.                     CHOOSER_PopUp,     TRUE,
  526.                     CHOOSER_Labels,    &ChooserList,
  527.                     CHOOSER_Selected,  size.view,
  528.                     TAG_END
  529.                 ),
  530.                 CHILD_WeightedWidth,   0,
  531.                 LAYOUT_AddChild,       size_gadgets[GID_8_CB2] =
  532.                 NewObject
  533.                 (   CHECKBOX_GetClass(),NULL,
  534.                     // checkbox
  535.                     GA_ID,             GID_8_CB2,
  536.                     GA_RelVerify,      TRUE,
  537.                     GA_Text,           "Include _slack?",
  538.                     GA_Selected,       (BOOL) size.slack,
  539.                 TAG_END),
  540.                 CHILD_WeightedWidth,   0,
  541.                 LAYOUT_AddImage,       NewObject
  542.                 (   LABEL_GetClass(),  NULL,
  543.                     LABEL_Text,        "",
  544.                     TAG_END
  545.                 ),
  546.                 CHILD_WeightedWidth,   100,
  547.             TAG_END),
  548.             CHILD_WeightedHeight,     0,
  549.             LAYOUT_AddChild,          size_gadgets[GID_8_CB3] =
  550.             NewObject
  551.             (   CHECKBOX_GetClass(),  NULL,
  552.                 GA_ID,                GID_8_CB3,
  553.                 GA_RelVerify,         TRUE,
  554.                 GA_Text,              "Fi_x protection bits?",
  555.                 GA_Selected,          (BOOL) size.fixprot,
  556.             TAG_END),
  557.             CHILD_WeightedHeight,     0,
  558.             LAYOUT_AddChild,          size_gadgets[GID_8_FG1] =
  559.             NewObject
  560.             (   FUELGAUGE_GetClass(), NULL,
  561.                 GA_ID,                GID_8_FG1,
  562.                 GA_Text,              "Ready.",
  563.                 FUELGAUGE_Level,      0,
  564.                 FUELGAUGE_Percent,    FALSE,
  565.                 FUELGAUGE_Justification,FGJ_CENTER,
  566.             TAG_END),
  567.             CHILD_WeightedHeight,     0,
  568.             LAYOUT_AddChild,
  569.             NewObject
  570.             (   LAYOUT_GetClass(),    NULL,
  571.                 LAYOUT_Orientation,   LAYOUT_ORIENT_HORIZ,
  572.                 LAYOUT_VertAlignment, LALIGN_CENTER,
  573.                 LAYOUT_HorizAlignment,LALIGN_CENTER,
  574.                 LAYOUT_BevelStyle,    BVS_NONE,
  575.                 LAYOUT_AddChild,      size_gadgets[GID_8_BU4] =
  576.                 NewObject
  577.                 (   NULL,             "button.gadget",
  578.                     GA_ID,            GID_8_BU4,
  579.                     GA_RelVerify,     TRUE,
  580.                     GA_Text,          "_Update",
  581.                 TAG_END),
  582.                 LAYOUT_AddChild,      size_gadgets[GID_8_BU5] =
  583.                 NewObject
  584.                 (   NULL,             "button.gadget",
  585.                     GA_ID,            GID_8_BU5,
  586.                     GA_RelVerify,     TRUE,
  587.                     GA_Text,          "Stop",
  588.                     GA_Disabled,      TRUE,
  589.                 TAG_END),
  590.             TAG_END),
  591.             CHILD_WeightedHeight,     0,
  592.     TAG_END)
  593.     )))
  594.     {   rq("Can't create ReAction objects!");
  595.     }
  596.     unlockscreen();
  597.     openwindow();
  598.     ActivateLayoutGadget(size_gadgets[GID_8_LY1], MainWindowPtr, NULL, (Object) size_gadgets[GID_8_ST1]);
  599.  
  600.     loop();
  601.     closewindow();
  602.     size_exit();
  603. }
  604.  
  605. AGLOBAL void updatesize(void)
  606. {   ABOOL                 failed      = FALSE;
  607.     struct FileInfoBlock* FIBPtr      = NULL;
  608.     struct InfoData*      InfoDataPtr;
  609.     struct ExAllControl*  eac;
  610.     struct SpecialNode*   NodePtr;
  611.  
  612.     ghost();
  613.     SetGadgetAttrs
  614.     (   size_gadgets[GID_8_FG1], MainWindowPtr, NULL,
  615.         FUELGAUGE_Min,   0,
  616.         FUELGAUGE_Max,   100,
  617.         FUELGAUGE_Level, 12,
  618.         GA_Text,         "Initializing...",
  619.         TAG_END
  620.     );
  621.  
  622.     killsizelist();
  623.     if ((List1.lh_Head)->ln_Succ) // the list is non-empty
  624.     {   FreeSpecialNodes(&List1);
  625.     }
  626.     if ((List2.lh_Head)->ln_Succ) // the list is non-empty
  627.     {   FreeSpecialNodes(&List2);
  628.     }
  629.     topnesting = 0;
  630.  
  631.     // 1: Ghost relevant gadgets, for duration of the operation.
  632.  
  633.     SetGadgetAttrs
  634.     (   size_gadgets[GID_8_FG1], MainWindowPtr, NULL,
  635.         FUELGAUGE_Min,   0,
  636.         FUELGAUGE_Max,   100,
  637.         FUELGAUGE_Level, 33,
  638.         GA_Text,         "Reading directories...",
  639.         TAG_END
  640.     ); // we don't know how many files in advance...
  641.  
  642.     // 2: Now get a Lock() on the path.
  643.  
  644.     size.numdirs = size.numfiles = 0;
  645.     /* From RKRM I&A, p. 65: */
  646.     if
  647.     (   !(DirHandle = (BPTR) Lock(size.path, ACCESS_READ))
  648.      || !(FIBPtr    = AllocDosObject(DOS_FIB, NULL))
  649.      || !(            Examine(DirHandle, FIBPtr))
  650.      ||  (FIBPtr->fib_DirEntryType <= 0) // if not a directory
  651.     )
  652.     {   failed = TRUE;
  653.     }
  654.  
  655.     strcpy(size.oldpath, size.path);
  656.     if (FIBPtr)
  657.     {   FreeDosObject(DOS_FIB, FIBPtr);
  658.         // FIBPtr = NULL;
  659.     }
  660.     if (failed)
  661.     {   DisplayBeep(ScreenPtr);
  662.         unghost();
  663.  
  664.         strcpy(size.path, size.oldpath);
  665.         SetGadgetAttrs
  666.         (   size_gadgets[GID_8_ST1], MainWindowPtr, NULL,
  667.             STRINGA_TextVal, size.path,
  668.             TAG_END
  669.         );
  670.         SetGadgetAttrs
  671.         (   size_gadgets[GID_8_FG1], MainWindowPtr, NULL,
  672.             FUELGAUGE_Level, 0,
  673.             GA_Text,         "Failed!",
  674.             TAG_END
  675.         );
  676.         return;
  677.     }
  678.     SetGadgetAttrs
  679.     (   size_gadgets[GID_8_ST1], MainWindowPtr, NULL,
  680.         STRINGA_TextVal, size.path,
  681.         TAG_END
  682.     );
  683.  
  684.     /* 3: Now we call Info() to ascertain the free bytes.
  685.           InfoDataPtr must be longword-aligned. */
  686.  
  687.     if (!(InfoDataPtr = AllocVec(sizeof(struct InfoData), MEMF_CLEAR | MEMF_PUBLIC)))
  688.     {   rq("Out of memory!");
  689.     }
  690.     if (Info(DirHandle, InfoDataPtr))
  691.     {   size.blocksize = InfoDataPtr->id_BytesPerBlock;
  692.         size.free      =
  693.         (InfoDataPtr->id_NumBlocks - InfoDataPtr->id_NumBlocksUsed) *
  694.          InfoDataPtr->id_BytesPerBlock;
  695.         size.capacity  =
  696.          InfoDataPtr->id_NumBlocks *
  697.          InfoDataPtr->id_BytesPerBlock;
  698.     } else
  699.     {   rq("Can't get volume info!");
  700.     }
  701.     FreeVec(InfoDataPtr);
  702.     // InfoDataPtr = NULL;
  703.  
  704.     comma(size.blocksize, commastring);
  705.     SetGadgetAttrs // "dirs"
  706.     (   size_gadgets[GID_8_ST8], MainWindowPtr, NULL,
  707.         STRINGA_TextVal, commastring,
  708.         TAG_END
  709.     );
  710.  
  711.     /* 4: Now we are ready to begin the main part of the operation. */
  712.  
  713.     size.slacktotal = size.unslacktotal = 0;
  714.  
  715.     // This must be allocated with AllocDosObject()
  716.     if (!(eac = AllocDosObject(DOS_EXALLCONTROL, NULL)))
  717.     {   rq("Can't allocate DOS object!");
  718.     }
  719.  
  720.     // examine path
  721.     AddSpecialNode(&List1, "", 0, 0, 0, 0, 0, ST_USERDIR, 0);
  722.     key = 0;
  723.     for (NodePtr = List1.lh_Head; NodePtr->Node.ln_Succ; NodePtr = NodePtr->Node.ln_Succ)
  724.     {   if (NodePtr->type == ST_USERDIR)
  725.         {   examine
  726.             (   NodePtr->pathname,
  727.                 NodePtr->nesting,
  728.                 NodePtr->key
  729.             );
  730.     }   }
  731.  
  732.     if (status == STATUS_BUSY)
  733.     {   busy();
  734.     }
  735.  
  736.     if (status != STATUS_BUSY)
  737.     {   SetGadgetAttrs // "used in path"
  738.         (   size_gadgets[GID_8_ST4], MainWindowPtr, NULL,
  739.             STRINGA_TextVal, "-",
  740.             TAG_END
  741.         );
  742.         SetGadgetAttrs // "free on volume"
  743.         (   size_gadgets[GID_8_ST5], MainWindowPtr, NULL,
  744.             STRINGA_TextVal, "-",
  745.             TAG_END
  746.         );
  747.         SetGadgetAttrs // "volume capacity"
  748.         (   size_gadgets[GID_8_ST3], MainWindowPtr, NULL,
  749.             STRINGA_TextVal, "-",
  750.             TAG_END
  751.         );
  752.         SetGadgetAttrs // "files"
  753.         (   size_gadgets[GID_8_ST6], MainWindowPtr, NULL,
  754.             STRINGA_TextVal, "-",
  755.             TAG_END
  756.         );
  757.         SetGadgetAttrs // "directories"
  758.         (   size_gadgets[GID_8_ST7], MainWindowPtr, NULL,
  759.             STRINGA_TextVal, "-",
  760.             TAG_END
  761.         );
  762.         SetGadgetAttrs // "block size"
  763.         (   size_gadgets[GID_8_ST8], MainWindowPtr, NULL,
  764.             STRINGA_TextVal, "-",
  765.             TAG_END
  766.         );
  767.         killsizelist();
  768.         SetGadgetAttrs
  769.         (   size_gadgets[GID_8_FG1], MainWindowPtr, NULL,
  770.             FUELGAUGE_Min,     0,
  771.             FUELGAUGE_Max,   100,
  772.             FUELGAUGE_Level,   0,
  773.             GA_Text,         "Aborted by user!",
  774.             TAG_END
  775.         );
  776.     }
  777.  
  778.     unghost();
  779.  
  780.     if (LogFileHandle)
  781.     {   Close(LogFileHandle);
  782.         LogFileHandle = NULL;
  783. }   }
  784.  
  785. AGLOBAL void size_loop(ULONG gid)
  786. {   ULONG                   i, length;
  787.     STRPTR                  stringptr;
  788.     struct ListBrowserNode* NodePtr;
  789.  
  790.     switch(gid)
  791.     {
  792.     case GID_8_BU1: // path ASL
  793.         pathasl();
  794.     break;
  795.     case GID_8_BU3:
  796.         asl("~(#?.info)");
  797.         SetGadgetAttrs // `Log to file:' (string)
  798.         (   size_gadgets[GID_8_ST2], MainWindowPtr, NULL,
  799.             STRINGA_TextVal, size.logfile,
  800.         TAG_END);
  801.     break;
  802.     case GID_8_BU4: // update
  803.         updatesize();
  804.     break;
  805.     // GID_8_BU5 is stop
  806.     case GID_8_BU6:
  807.         root();
  808.     break;
  809.     case GID_8_BU7:
  810.         parent();
  811.     break;
  812.     case GID_8_ST1: // path string
  813.         if (!(GetAttr
  814.         (   STRINGA_TextVal, size_gadgets[GID_8_ST1], (ULONG *) &stringptr
  815.         )))
  816.         {   rq("Unsupported inquiry!"); // should never happen
  817.         }
  818.         strcpy(size.path, stringptr);
  819.         updatesize();
  820.     break;
  821.     case GID_8_ST2: // output string
  822.         if (!(GetAttr
  823.         (   STRINGA_TextVal, size_gadgets[GID_8_ST2], (ULONG *) &stringptr
  824.         )))
  825.         {   rq("Unsupported inquiry!"); // should never happen
  826.         }
  827.         strcpy(size.logfile, stringptr);
  828.     break;
  829.     case GID_8_CB1:
  830.         if (!(GetAttr
  831.         (   GA_Selected, size_gadgets[GID_8_CB1], &size.log
  832.         )))
  833.         {   rq("Unsupported inquiry!"); // should never happen
  834.         }
  835.  
  836.         SetGadgetAttrs // `Log to file:' (string)
  837.         (   size_gadgets[GID_8_ST2], MainWindowPtr, NULL,
  838.             GA_Disabled, !size.log,
  839.             TAG_END
  840.         );
  841.         /* For some reason, we need to explicitly refresh the string gadget
  842.         visuals here */
  843.         RefreshGadgets((struct Gadget *) size_gadgets[GID_8_ST2], MainWindowPtr, NULL);
  844.  
  845.         SetGadgetAttrs // `Log to file:' (ASL button)
  846.         (   size_gadgets[GID_8_BU3], MainWindowPtr, NULL,
  847.             GA_Disabled, !size.log,
  848.             TAG_END
  849.         );
  850.         if (size.log)
  851.         {   ActivateLayoutGadget(size_gadgets[GID_8_LY1], MainWindowPtr, NULL, (Object) size_gadgets[GID_8_ST2]);
  852.         }
  853.     break;
  854.     case GID_8_CB2:
  855.         if (!(GetAttr
  856.         (   GA_Selected, size_gadgets[GID_8_CB2], (ULONG *) &size.slack
  857.         )))
  858.         {   rq("Unsupported inquiry!"); // should never happen
  859.         }
  860.         print_list(TRUE);
  861.     break;
  862.     case GID_8_CB3:
  863.         if (!(GetAttr
  864.         (   GA_Selected, size_gadgets[GID_8_CB3], (ULONG *) &size.fixprot
  865.         )))
  866.         {   rq("Unsupported inquiry!"); // should never happen
  867.         }
  868.     break;
  869.     case GID_8_CB4:
  870.         if (!(GetAttr
  871.         (   GA_Selected, size_gadgets[GID_8_CB4], (ULONG *) &showall
  872.         )))
  873.         {   rq("Unsupported inquiry!"); // should never happen
  874.         }
  875.         print_list(TRUE);
  876.     break;
  877.     case GID_8_CB5:
  878.         if (!(GetAttr
  879.         (   GA_Selected, size_gadgets[GID_8_CB5], (ULONG *) &showfiles
  880.         )))
  881.         {   rq("Unsupported inquiry!"); // should never happen
  882.         }
  883.         print_list(TRUE);
  884.     break;      
  885.     case GID_8_CH1:
  886.         if (!(GetAttr
  887.         (   CHOOSER_Selected, size_gadgets[GID_8_CH1], (ULONG *) &size.view
  888.         )))
  889.         {   rq("Unsupported inquiry!"); // should never happen
  890.         }
  891.         print_list(TRUE);
  892.     break;
  893.     case GID_8_LB2:
  894.         // We get a message even if the user clicked on an empty part of
  895.         // the gadget.
  896.  
  897.         if (!(GetAttr
  898.         (   LISTBROWSER_SelectedNode, size_gadgets[GID_8_LB2], (ULONG *) &NodePtr
  899.         )))
  900.         {   rq("Unsupported inquiry!"); // should never happen
  901.         }
  902.         if (NodePtr)
  903.         {   GetListBrowserNodeAttrs((struct Node *) NodePtr, LBNA_Column, 0, LBNCA_Text, &stringptr, TAG_DONE);
  904.             length = strlen(stringptr);
  905.             for (i = 0; i <= length; i++)
  906.             {   if (*(stringptr + i) == '*')
  907.                 {   if (!(AddPart(size.path, stringptr + i + 1, PATHNAMEFIELD)))
  908.                     {   rq("Can't add filename to pathname!");
  909.                     }
  910.                     updatesize();
  911.                     break;
  912.         }   }   }
  913.     break;
  914.     default:
  915.     break;
  916. }   }
  917.  
  918. AGLOBAL void size_exit(void)
  919. {   if (DirHandle)
  920.     {   UnLock(DirHandle);
  921.         DirHandle = NULL;
  922.     }
  923.     if (LogFileHandle)
  924.     {   Close(LogFileHandle);
  925.         LogFileHandle = NULL;
  926.     }
  927.     if ((List1.lh_Head)->ln_Succ) // the list is non-empty
  928.     {   FreeSpecialNodes(&List1);
  929.     }
  930.     if ((List2.lh_Head)->ln_Succ) // the list is non-empty
  931.     {   FreeSpecialNodes(&List2);
  932.     }
  933.  
  934.     // Only call this if the list gadget is detached or not present.
  935.     // (ie. after closewindow()).
  936.     if ((SizeList.lh_Head)->ln_Succ) // if the list is non-empty
  937.     {   clearreactionlist(&SizeList);
  938. }   }
  939.  
  940. AGLOBAL void size_die(void)
  941. {   if ((EmptySizeList.lh_Head)->ln_Succ) // if the list is non-empty
  942.     {   clearreactionlist(&EmptySizeList);
  943.     }
  944.  
  945.     IOBuffer[0]  = (UBYTE) size.log;
  946.     IOBuffer[6]  = (UBYTE) showfiles;
  947.     IOBuffer[15] = (UBYTE) showall;
  948.     IOBuffer[21] = (UBYTE) size.slack;
  949.     IOBuffer[22] = (UBYTE) size.view;
  950.     IOBuffer[24] = (UBYTE) size.fixprot;
  951. }
  952.  
  953. AGLOBAL void size_config(void)
  954. {   size.log     = (ULONG) IOBuffer[0];
  955.     showfiles    = (ULONG) IOBuffer[6];
  956.     showall      = (ULONG) IOBuffer[15];
  957.     size.slack   = (ULONG) IOBuffer[21];
  958.     size.view    = (ULONG) IOBuffer[22];
  959.     size.fixprot = (ULONG) IOBuffer[24];
  960. }
  961.  
  962. MODULE void parent(void)
  963. {   BPTR DirHandle,
  964.          ParentHandle;
  965.  
  966.     if (!(DirHandle = (BPTR) Lock(size.path, ACCESS_READ)))
  967.         rq("Can't lock directory!");
  968.     if (!(ParentHandle = ParentDir(DirHandle)))
  969.     {   /* It returned a NULL lock; ie. a lock on SYS:
  970.         That is not what we want. */
  971.         ParentHandle = DirHandle;
  972.     }
  973.     if (!NameFromLock(ParentHandle, size.path, PATHNAMEFIELD))
  974.         rq("Can't get name from lock!");
  975.     UnLock(DirHandle);
  976.     // DirHandle = NULL;
  977.  
  978.     updatesize();
  979. }
  980.  
  981. MODULE void root(void)
  982. {   BPTR  DirHandle,
  983.           ParentHandle;
  984.     ABOOL rootdone     = FALSE;
  985.  
  986.     if (!(DirHandle = (BPTR) Lock(size.path, ACCESS_READ)))
  987.         rq("Can't lock directory!");
  988.     do
  989.     {   if (!(ParentHandle = ParentDir(DirHandle)))
  990.         {   /* It returned a NULL lock; ie. a lock on SYS:
  991.                That is not what we want. */
  992.             ParentHandle = DirHandle;
  993.             rootdone = TRUE;
  994.         } else DirHandle = ParentHandle;
  995.     } while (!rootdone);
  996.     if (!NameFromLock(ParentHandle, size.path, PATHNAMEFIELD))
  997.         rq("Can't get name from lock!");
  998.     UnLock(DirHandle);
  999.     // DirHandle = NULL;
  1000.  
  1001.     updatesize();
  1002. }
  1003.  
  1004. MODULE void pathasl(void)
  1005. {   strcpy(asldir, size.path);
  1006.     if (dirasl()) // path for ASL must be valid?
  1007.     {   strcpy(size.path, aslresult);
  1008.         SetGadgetAttrs
  1009.         (   size_gadgets[GID_8_ST1], MainWindowPtr, NULL,
  1010.             STRINGA_TextVal, size.path,
  1011.             TAG_END
  1012.         );
  1013.         updatesize();
  1014. }   }
  1015.  
  1016. MODULE void writeline(void)
  1017. {   /* The file is opened just before the first call to writeline()
  1018.     (when the date, time, etc. is written). Then we keep the file open
  1019.     and do our scan. Then we write out the results a line at a time,
  1020.     then the free and total bytes. */
  1021.  
  1022.     if (FPuts(LogFileHandle, logstring))
  1023.     {   Close(LogFileHandle);
  1024.         LogFileHandle = NULL;
  1025.         rq("Can't append to file!");
  1026. }   }
  1027.  
  1028. MODULE void killsizelist(void)
  1029. {   SetGadgetAttrs
  1030.     (   size_gadgets[GID_8_LB2], MainWindowPtr, NULL,
  1031.         LISTBROWSER_Labels, &EmptySizeList,
  1032.         TAG_END
  1033.     );
  1034.     if ((SizeList.lh_Head)->ln_Succ) // if the list is non-empty
  1035.     {   clearreactionlist(&SizeList);
  1036. }   }
  1037.  
  1038. AGLOBAL ULONG Hook8Func(struct Hook *h, VOID *o, VOID *msg)
  1039. {   /* "When the hook is called, the data argument points to the
  1040.     window object and message argument to the IntuiMessage." */
  1041.  
  1042.     UWORD code, qual;
  1043.     ULONG scroll = 0; // to avoid spurious compiler warnings
  1044.  
  1045.     geta4(); // wait till here before doing anything
  1046.     code = ((struct IntuiMessage *) msg)->Code;
  1047.     qual = ((struct IntuiMessage *) msg)->Qualifier;
  1048.     switch(code)
  1049.     {
  1050.     case SCAN_HELP:
  1051.         if (status == STATUS_READY)
  1052.         {   helpabout();
  1053.         }
  1054.     break;
  1055.     case SCAN_ESCAPE:
  1056.         if (status == STATUS_READY)
  1057.         {   if ((qual & IEQUALIFIER_LSHIFT) || (qual & IEQUALIFIER_RSHIFT))
  1058.             {   cleanexit(EXIT_SUCCESS);
  1059.             } else page = 0;
  1060.         } else
  1061.         {   // assert(status == STATUS_BUSY);
  1062.             status = STATUS_STOPPING;
  1063.         }
  1064.     break;
  1065.     case SCAN_P:
  1066.         ActivateLayoutGadget(size_gadgets[GID_8_LY1], MainWindowPtr, NULL, (Object) size_gadgets[GID_8_ST1]);
  1067.     break;
  1068.     case SCAN_V:
  1069.         if (status == STATUS_READY)
  1070.         {   if (!(qual & IEQUALIFIER_LSHIFT) && !(qual & IEQUALIFIER_RSHIFT))
  1071.             {   if (size.view < UNITOPTIONS)
  1072.                     size.view++;
  1073.                 else size.view = 0;
  1074.             } else
  1075.             {   if (size.view > 0)
  1076.                     size.view--;
  1077.                 else size.view = UNITOPTIONS;
  1078.             }
  1079.             SetGadgetAttrs
  1080.             (   size_gadgets[GID_8_CH1], MainWindowPtr, NULL,
  1081.                 CHOOSER_Selected, size.view,
  1082.                 TAG_END
  1083.             );
  1084.         }
  1085.         print_list(TRUE);
  1086.     break;
  1087.     case SCAN_PERIOD:
  1088.         pathasl();
  1089.     break;
  1090.     case SCAN_UP:
  1091.         if (qual & IEQUALIFIER_CONTROL)
  1092.         {   scroll = LBP_TOP;
  1093.         } elif (qual & IEQUALIFIER_LSHIFT || qual & IEQUALIFIER_RSHIFT)
  1094.         {   scroll = LBP_PAGEUP;
  1095.         } else scroll = LBP_LINEUP;
  1096.     break;
  1097.     case SCAN_DOWN:
  1098.         if (qual & IEQUALIFIER_CONTROL)
  1099.         {   scroll = LBP_BOTTOM;
  1100.         } elif (qual & IEQUALIFIER_LSHIFT || qual & IEQUALIFIER_RSHIFT)
  1101.         {   scroll = LBP_PAGEDOWN;
  1102.         } else scroll = LBP_LINEDOWN;
  1103.     break;
  1104.     default:
  1105.     break;
  1106.     }
  1107.  
  1108.     if (code == SCAN_UP || code == SCAN_DOWN)
  1109.     {   SetGadgetAttrs
  1110.         (   size_gadgets[GID_8_LB2],      // pointer to gadget
  1111.             MainWindowPtr,                // pointer to window (not window object!)
  1112.             NULL,                         // pointer to requester
  1113.             LISTBROWSER_Position, scroll, // tags
  1114.             TAG_DONE                      // done
  1115.         );
  1116.     }
  1117.  
  1118.     return(1);
  1119. }
  1120.  
  1121. MODULE void ghost(void)
  1122. {   status = STATUS_BUSY;
  1123.  
  1124.     SetGadgetAttrs // "update"
  1125.     (   size_gadgets[GID_8_BU4], MainWindowPtr, NULL,
  1126.         GA_Disabled, TRUE,
  1127.         TAG_END
  1128.     );
  1129.     SetGadgetAttrs // "stop"
  1130.     (   size_gadgets[GID_8_BU5], MainWindowPtr, NULL,
  1131.         GA_Disabled, FALSE,
  1132.         TAG_END
  1133.     );
  1134. }
  1135.  
  1136. MODULE void unghost(void)
  1137. {   status = STATUS_READY;
  1138.  
  1139.     SetGadgetAttrs // "update"
  1140.     (   size_gadgets[GID_8_BU4], MainWindowPtr, NULL,
  1141.         GA_Disabled, FALSE,
  1142.         TAG_END
  1143.     );
  1144.     SetGadgetAttrs // "stop"
  1145.     (   size_gadgets[GID_8_BU5], MainWindowPtr, NULL,
  1146.         GA_Disabled, TRUE,
  1147.         TAG_END
  1148.     );
  1149. }
  1150.  
  1151. MODULE void scale(ULONG bytes)
  1152. {   if (size.view == 0) // bytes
  1153.     {   comma(bytes, commastring);
  1154.     } elif (size.view == 1) // kilobytes
  1155.     {   comma(bytes / 1024, commastring);
  1156.     } elif (size.view == 2) // megabytes
  1157.     {   comma(bytes / 1048576, commastring);
  1158.     } else
  1159.     {   // assert(size.view == 3); // blocks
  1160.         // assert(size.blocksize); // to avoid division by zero
  1161.         comma(bytes / size.blocksize, commastring);
  1162.         if (bytes % size.blocksize)
  1163.         {   comma((bytes / size.blocksize) + 1, commastring);
  1164.         } else // exactly on a block boundary
  1165.         {   comma(bytes / size.blocksize, commastring);
  1166. }   }   }
  1167.  
  1168. /*
  1169. MODULE void __inline progressbar(ULONG level)
  1170. {   if (!(level % increment))
  1171.     {   SetGadgetAttrs
  1172.         (   size_gadgets[GID_8_FG1], MainWindowPtr, NULL,
  1173.             FUELGAUGE_Level, level,
  1174.             TAG_END
  1175.         );
  1176. }   }
  1177. */
  1178.  
  1179. MODULE void examine(STRPTR thename, ULONG nesting, ULONG parentdir)
  1180. {   BOOL                 more;      // BOOL, not ABOOL
  1181.     BPTR                 DirHandle; // = NULL;
  1182.     struct ExAllControl* eac;       // = NULL;
  1183.     struct ExAllData*    ead;
  1184.     ULONG                baselength    = strlen(size.path),
  1185.                          breakval,
  1186.                          unslacksize,
  1187.                          slacksize;
  1188.     TEXT                 activefile[PATHNAMEFIELD + 1],
  1189.                          lockstring[PATHNAMEFIELD + 1];
  1190.     LONG                 ed,
  1191.                          prot;
  1192.  
  1193.     breakval = ra_checkbreak();
  1194.     if (breakval == 2)
  1195.     {   cleanexit(EXIT_SUCCESS);
  1196.     } elif (breakval == 1)
  1197.     {   status = STATUS_STOPPING;
  1198.         SetGadgetAttrs
  1199.         (   size_gadgets[GID_8_FG1], MainWindowPtr, NULL,
  1200.             GA_Text, "Stopping...",
  1201.             TAG_END
  1202.         );
  1203.     }
  1204.     if (status == STATUS_STOPPING)
  1205.     {   return;
  1206.     }
  1207.  
  1208.     strcpy(lockstring, size.path);
  1209.     strcat(lockstring, thename);
  1210.  
  1211.     if (!(DirHandle = (BPTR) Lock(lockstring, ACCESS_READ)))
  1212.     {   // Printf("Can't lock %s!\n", lockstring);
  1213.         rq("Can't lock directory!");
  1214.     }
  1215.     if (!(eac = AllocDosObject(DOS_EXALLCONTROL, NULL)))
  1216.     {   UnLock(DirHandle);
  1217.         DirHandle = NULL;
  1218.         rq("Can't allocate DOS object!");
  1219.     }
  1220.  
  1221.     if (size.fixprot)
  1222.     {   ed = ED_PROTECTION; // we want name, type, size and protection
  1223.     } else
  1224.     {   ed = ED_SIZE;       // we want name, type and size
  1225.     }
  1226.  
  1227.     eac->eac_LastKey = 0;
  1228.     do
  1229.     {   more = ExAll(DirHandle, (struct ExAllData *) EADataPtr, 4096, ed, eac);
  1230.         if (!more && IoErr() != ERROR_NO_MORE_ENTRIES)
  1231.         {   FreeDosObject(DOS_EXALLCONTROL, eac);
  1232.             eac = NULL;
  1233.             UnLock(DirHandle);
  1234.             DirHandle = NULL;
  1235.             rq("Can't examine path!"); /* ExAll() failed abnormally */
  1236.         }
  1237.         if (eac->eac_Entries == 0)
  1238.         {   ; /* ExAll() failed normally with no entries */
  1239.             continue; /* more is USUALLY zero */
  1240.         }
  1241.         ead = (struct ExAllData *) EADataPtr;
  1242.  
  1243.         do
  1244.         {   /* use ead here */
  1245.  
  1246.             strcpy(activefile, lockstring);
  1247.             if (!AddPart(activefile, ead->ed_Name, PATHNAMEFIELD))
  1248.             {   FreeDosObject(DOS_EXALLCONTROL, eac);
  1249.                 eac = NULL;
  1250.                 UnLock(DirHandle);
  1251.                 DirHandle = NULL;
  1252.                 rq("Can't add filename/dirname to path!");
  1253.             }
  1254.             if (ead->ed_Type == ST_USERDIR)
  1255.             {   size.numdirs++;
  1256.                 if (!(size.numdirs % GRANULARITY_DIRS))
  1257.                 {   comma(size.numdirs, commastring);
  1258.                     SetGadgetAttrs
  1259.                     (   size_gadgets[GID_8_ST7], MainWindowPtr, NULL,
  1260.                         STRINGA_TextVal, commastring,
  1261.                         TAG_END
  1262.                     );
  1263.                 }
  1264.  
  1265.                 AddSpecialNode
  1266.                 (   &List1,                      // list
  1267.                     &activefile[baselength],     // filename
  1268.                     nesting + 1,                 // nesting
  1269.                     0,                           // unslacksize
  1270.                     0,                           // slacksize
  1271.                     parentdir,                   // parentdir
  1272.                     ++key,                       // key
  1273.                     ST_USERDIR,                  // type
  1274.                     0                            // protection bits
  1275.                 );
  1276.                 if (topnesting < nesting + 1)
  1277.                 {   topnesting = nesting + 1;
  1278.             }   }
  1279.             elif (ead->ed_Type == ST_FILE)
  1280.             {   size.numfiles++;
  1281.                 if (!(size.numfiles % GRANULARITY_FILES))
  1282.                 {   comma(size.numfiles, commastring);
  1283.                     SetGadgetAttrs
  1284.                     (   size_gadgets[GID_8_ST6], MainWindowPtr, NULL,
  1285.                         STRINGA_TextVal, commastring,
  1286.                         TAG_END
  1287.                     );
  1288.                 }
  1289.                 if (ead->ed_Size % size.blocksize == 0)
  1290.                 {   slacksize = ead->ed_Size;
  1291.                 } else
  1292.                 {   slacksize = ((ead->ed_Size / size.blocksize) + 1) * size.blocksize;
  1293.                 }
  1294.                 unslacksize = ead->ed_Size;
  1295.                 size.unslacktotal += unslacksize;
  1296.                 size.slacktotal   += slacksize;
  1297.  
  1298.                 if (size.fixprot)
  1299.                 {   prot = ead->ed_Prot;
  1300.                 } else
  1301.                 {   prot = 0;
  1302.                 }
  1303.  
  1304.                 AddSpecialNode
  1305.                 (   &List1,                      // list
  1306.                     &activefile[baselength + 1], // filename
  1307.                     nesting + 1,                 // nesting
  1308.                     unslacksize,                 // unslacksize
  1309.                     slacksize,                   // slacksize
  1310.                     parentdir,                   // parentdir
  1311.                     ++key,                       // key
  1312.                     ST_FILE,                     // type
  1313.                     prot                         // protection bits
  1314.                 );
  1315.                 if (topnesting < nesting + 1)
  1316.                 {   topnesting = nesting + 1;
  1317.             }   }
  1318.  
  1319.             /* get next ead */
  1320.             ead = ead->ed_Next;
  1321.         } while(ead);
  1322.     } while(more);
  1323.  
  1324.     FreeDosObject(DOS_EXALLCONTROL, eac);
  1325.     // eac = NULL;
  1326.     UnLock(DirHandle);
  1327.     // DirHandle = NULL;
  1328. }
  1329.  
  1330. MODULE void AddSpecialNode(struct List* ListPtr, STRPTR pathname, ULONG nesting, ULONG unslacksize, ULONG slacksize, ULONG parentdir, ULONG key, LONG type, LONG prot)
  1331. {   struct SpecialNode* NodePtr;
  1332.     ULONG               needed;
  1333.  
  1334.     needed = sizeof(struct SpecialNode) + strlen(pathname);
  1335.  
  1336.     if (!(NodePtr = AllocVec(needed, MEMF_CLEAR | MEMF_PUBLIC)))
  1337.         rq("Out of memory!");
  1338.     strcpy(NodePtr->pathname, pathname);
  1339.     NodePtr->nesting      = nesting;
  1340.     NodePtr->unslacksize  = unslacksize;
  1341.     NodePtr->slacksize    = slacksize;
  1342.     NodePtr->parentdir    = parentdir;
  1343.     NodePtr->key          = key;
  1344.     NodePtr->type         = type;
  1345.     NodePtr->prot         = prot;
  1346.     NodePtr->Node.ln_Name = NULL;
  1347.     NodePtr->Node.ln_Type = NT_USER;
  1348.     NodePtr->Node.ln_Pri  = 0;
  1349.     AddTail((struct List *) ListPtr, (struct Node *) NodePtr);
  1350. }
  1351. MODULE void FreeSpecialNodes(struct List* ListPtr)
  1352. {   /* RKM Libraries, p. 496:
  1353.     
  1354.     "Free the entire list, including the header. The header is not
  1355.     updated as the list is freed. This function demonstrates how to
  1356.     avoid referencing freed memory when deallocating nodes." */
  1357.  
  1358.     struct SpecialNode *WorkNodePtr, *NextNodePtr;
  1359.     
  1360.     WorkNodePtr = (struct SpecialNode *) (ListPtr->lh_Head); /* first node */
  1361.     while (NextNodePtr = (struct SpecialNode *) (WorkNodePtr->Node.ln_Succ))
  1362.     {   FreeVec(WorkNodePtr);
  1363.         WorkNodePtr = NextNodePtr;
  1364.     }
  1365.     NewList(ListPtr);
  1366. }
  1367.  
  1368. MODULE void print_node(ULONG passedkey)
  1369. {   struct SpecialNode *NodePtr,
  1370.                        *ChildNodePtr;
  1371.  
  1372.     for (NodePtr = List2.lh_Head; NodePtr->Node.ln_Succ; NodePtr = NodePtr->Node.ln_Succ)
  1373.     {   if (NodePtr->key == passedkey)
  1374.         {   break;
  1375.     }   }
  1376.  
  1377.     if (NodePtr->key != 0)
  1378.     {   print_entry(NodePtr);
  1379.     }
  1380.  
  1381.     // print child dirs
  1382.     for (ChildNodePtr = List2.lh_Head; ChildNodePtr->Node.ln_Succ; ChildNodePtr = ChildNodePtr->Node.ln_Succ)
  1383.     {   if (ChildNodePtr->key != 0)
  1384.         {   if (ChildNodePtr->parentdir == passedkey && (showall || ChildNodePtr->nesting <= 1))
  1385.             {   if (ChildNodePtr->type == ST_USERDIR)
  1386.                 {   print_node(ChildNodePtr->key);
  1387.                 } elif (showfiles)
  1388.                 {   print_entry(ChildNodePtr);
  1389. }   }   }   }   }
  1390.  
  1391. MODULE void print_entry(struct SpecialNode* NodePtr)
  1392. {   ULONG                   i, length,
  1393.                             where = 0; // to avoid spurious compiler warnings
  1394.     struct ListBrowserNode* ListBrowserNodePtr;
  1395.  
  1396.     logstring[0] = 0;
  1397.     if (NodePtr->nesting >= 2)
  1398.     {   for (i = 2; i <= NodePtr->nesting; i++)
  1399.         {   strcat(logstring, " ");
  1400.     }   }
  1401.     if (NodePtr->type == ST_USERDIR)
  1402.     {   strcat(logstring, "*");
  1403.     } else
  1404.     {   strcat(logstring, " ");
  1405.     }
  1406.     
  1407.     strcat(logstring, FilePart(NodePtr->pathname));
  1408.  
  1409.     if (size.slack)
  1410.     {   scale(NodePtr->slacksize);
  1411.     } else
  1412.     {   scale(NodePtr->unslacksize);
  1413.     }
  1414.  
  1415.     for (i = 0; i <= 13; i++)
  1416.     {   if (commastring[i] != ' ')
  1417.         {   where = i; // where is index of first non-space character
  1418.             break;
  1419.     }   }
  1420.  
  1421.     if (!(ListBrowserNodePtr = AllocListBrowserNode
  1422.     (   2,                       // columns,
  1423.         LBNA_Column,             0,
  1424.             LBNCA_CopyText,      TRUE,
  1425.             LBNCA_Text,          logstring,
  1426.         LBNA_Column,             1,
  1427.             LBNCA_CopyText,      TRUE,
  1428.             LBNCA_Text,          &commastring[where],
  1429.             LBNCA_Justification, LCJ_RIGHT,
  1430.         TAG_END
  1431.     )))
  1432.     {   rq("Can't create ReAction listbrowser.gadget node(s)!");
  1433.     }
  1434.     AddTail(&SizeList, (struct Node *) ListBrowserNodePtr); // AddTail() has no return code
  1435.  
  1436.     if (size.log)
  1437.     {   length = strlen(logstring);
  1438.         if (length < 50)
  1439.         {   for (i = 1; i <= 41 - length; i++)
  1440.             {   strcat(logstring, " ");
  1441.         }   }
  1442.         strcat(logstring, commastring);
  1443.         strcat(logstring, "\n");
  1444.         writeline();
  1445. }   }
  1446.  
  1447. MODULE void print_list(ABOOL close)
  1448. {   getdate();
  1449.     if (size.log)
  1450.     {   strcpy(logstring, "Path: \"");
  1451.         strcat(logstring, size.path);
  1452.         strcat(logstring, "\" at ");
  1453.         strcat(logstring, timestring);
  1454.         strcat(logstring, " on ");
  1455.         strcat(logstring, weekdaystring);
  1456.         strcat(logstring, " ");
  1457.         strcat(logstring, datestring);
  1458.         strcat(logstring, ":\n");
  1459.         if (!(LogFileHandle = (BPTR) Open(size.logfile, MODE_READWRITE)))
  1460.             rq("Can't open file for appending!");
  1461.         Seek(LogFileHandle, 0, OFFSET_END);
  1462.         writeline();
  1463.     }
  1464.  
  1465.     SetGadgetAttrs
  1466.     (   size_gadgets[GID_8_FG1], MainWindowPtr, NULL,
  1467.         FUELGAUGE_Min,   0,
  1468.         FUELGAUGE_Max,   100,
  1469.         FUELGAUGE_Level, 90,
  1470.         GA_Text,         "Generating list...",
  1471.         TAG_END
  1472.     );
  1473.  
  1474.     if (close) // if only a list update rather than a full update
  1475.     {   ghost();
  1476.     }
  1477.     killsizelist();
  1478.     print_node(0);
  1479.  
  1480.     SetGadgetAttrs
  1481.     (   size_gadgets[GID_8_LB2], MainWindowPtr, NULL,
  1482.         LISTBROWSER_Labels, &SizeList,
  1483.         TAG_END
  1484.     );
  1485.  
  1486.     if (size.slack)
  1487.     {   scale(size.slacktotal);
  1488.     } else
  1489.     {   scale(size.unslacktotal);
  1490.     }
  1491.     SetGadgetAttrs // "used in path"
  1492.     (   size_gadgets[GID_8_ST4], MainWindowPtr, NULL,
  1493.         STRINGA_TextVal, commastring,
  1494.         TAG_END
  1495.     );
  1496.     scale(size.free);
  1497.     SetGadgetAttrs // "free on volume"
  1498.     (   size_gadgets[GID_8_ST5], MainWindowPtr, NULL,
  1499.         STRINGA_TextVal, commastring,
  1500.         TAG_END
  1501.     );
  1502.     scale(size.capacity);
  1503.     SetGadgetAttrs // "volume capacity"
  1504.     (   size_gadgets[GID_8_ST3], MainWindowPtr, NULL,
  1505.         STRINGA_TextVal, commastring,
  1506.         TAG_END
  1507.     );
  1508.     comma(size.numfiles, commastring);
  1509.     SetGadgetAttrs // "files"
  1510.     (   size_gadgets[GID_8_ST6], MainWindowPtr, NULL,
  1511.         STRINGA_TextVal, commastring,
  1512.         TAG_END
  1513.     );
  1514.     comma(size.numdirs, commastring);
  1515.     SetGadgetAttrs // "dirs"
  1516.     (   size_gadgets[GID_8_ST7], MainWindowPtr, NULL,
  1517.         STRINGA_TextVal, commastring,
  1518.         TAG_END
  1519.     );
  1520.  
  1521.     if (size.log)
  1522.     {   strcpy(logstring, "\nUsed in path:                            ");
  1523.         if (size.slack)
  1524.         {   scale(size.slacktotal);
  1525.         } else
  1526.         {   scale(size.unslacktotal);
  1527.         }
  1528.         strcat(logstring, commastring);
  1529.         strcat(logstring, "\nFree on volume:                          "); // these must be adjusted according to TRUNCATE
  1530.         scale(size.free);
  1531.         strcat(logstring, commastring);
  1532.         strcat(logstring, "\nVolume capacity:                         "); // these must be adjusted according to TRUNCATE
  1533.         scale(size.capacity);
  1534.         strcat(logstring, commastring);
  1535.         strcat(logstring, "\nFiles:                                   "); // these must be adjusted according to TRUNCATE
  1536.         comma(size.numfiles, commastring);
  1537.         strcat(logstring, commastring);
  1538.         strcat(logstring, "\nDirectories:                             "); // these must be adjusted according to TRUNCATE
  1539.         comma(size.numdirs, commastring);
  1540.         strcat(logstring, commastring);
  1541.         strcat(logstring, "\nBlock size:                              "); // these must be adjusted according to TRUNCATE
  1542.         comma(size.blocksize, commastring);
  1543.         strcat(logstring, commastring);
  1544.         strcat(logstring, "\n\n");
  1545.         writeline();
  1546.     }
  1547.     if (close && LogFileHandle)
  1548.     {   Close(LogFileHandle);
  1549.         LogFileHandle = NULL;
  1550.     }
  1551.     SetGadgetAttrs
  1552.     (   size_gadgets[GID_8_FG1], MainWindowPtr, NULL,
  1553.         FUELGAUGE_Min,     0,
  1554.         FUELGAUGE_Max,   100,
  1555.         FUELGAUGE_Level, 100,
  1556.         GA_Text,         "Done.",
  1557.         TAG_END
  1558.     );
  1559.     if (close) // if only a list update rather than a full update
  1560.     {   unghost();
  1561. }   }
  1562.  
  1563. MODULE void busy(void)
  1564. {   ULONG               breakval, largestsize,
  1565.                         largestkey = 0; // to avoid spurious compiler warnings
  1566.     SLONG               nesting;
  1567.     struct SpecialNode *NodePtr,
  1568.                        *ParentNodePtr;
  1569.     TEXT                activefile[PATHNAMEFIELD + 1];
  1570.  
  1571.     if (size.fixprot)
  1572.     {   SetGadgetAttrs
  1573.         (   size_gadgets[GID_8_FG1], MainWindowPtr, NULL,
  1574.             FUELGAUGE_Min,   0,
  1575.             FUELGAUGE_Max,   100,
  1576.             FUELGAUGE_Level, 45,
  1577.             GA_Text,         "Fixing protection bits...",
  1578.             TAG_END
  1579.         );
  1580.  
  1581.         if ((List1.lh_Head)->ln_Succ) // the list is non-empty
  1582.         {   // walk the files list
  1583.             for (NodePtr = List1.lh_Head; NodePtr->Node.ln_Succ; NodePtr = NodePtr->Node.ln_Succ)
  1584.             {   if (NodePtr->type == ST_FILE)
  1585.                 {   /* The rwed bits are SET to DENY access,
  1586.                     CLEARED to PERMIT access.
  1587.  
  1588.                     128 064 032 016 008 004 002 001
  1589.                     -H- -S- -P- -A- -R- -W- -E- -D- */
  1590.  
  1591.                     if
  1592.                     (   (NodePtr->prot & FIBF_READ)
  1593.                      || (NodePtr->prot & FIBF_WRITE)
  1594.                      || (NodePtr->prot & FIBF_EXECUTE)
  1595.                      || (NodePtr->prot & FIBF_DELETE)
  1596.                     )
  1597.                     {   NodePtr->prot &= ~FIBF_READ;
  1598.                         NodePtr->prot &= ~FIBF_WRITE;
  1599.                         NodePtr->prot &= ~FIBF_EXECUTE;
  1600.                         NodePtr->prot &= ~FIBF_DELETE;
  1601.  
  1602.                         strcpy(activefile, size.path);
  1603.                         if (!AddPart(activefile, NodePtr->pathname, PATHNAMEFIELD))
  1604.                         {   rq("Can't add filename to pathname!");
  1605.                         }
  1606.  
  1607.                         if (!(SetProtection(activefile, NodePtr->prot)))
  1608.                         {   rq("Can't fix protection bits!");
  1609.     }   }   }   }   }   }
  1610.  
  1611.     SetGadgetAttrs
  1612.     (   size_gadgets[GID_8_FG1], MainWindowPtr, NULL,
  1613.         FUELGAUGE_Min,   0,
  1614.         FUELGAUGE_Max,   100,
  1615.         FUELGAUGE_Level, 50,
  1616.         GA_Text,         "Calculating sizes...",
  1617.         TAG_END
  1618.     );
  1619.  
  1620.     // calculate sizes
  1621.     for (nesting = topnesting; nesting >= 0; nesting--)
  1622.     {   breakval = ra_checkbreak();
  1623.         if (breakval == 2)
  1624.         {   cleanexit(EXIT_SUCCESS);
  1625.         } elif (breakval == 1)
  1626.         {   status = STATUS_STOPPING;
  1627.             SetGadgetAttrs
  1628.             (   size_gadgets[GID_8_FG1], MainWindowPtr, NULL,
  1629.                 GA_Text, "Stopping...",
  1630.                 TAG_END
  1631.             );
  1632.         }
  1633.         if (status == STATUS_STOPPING)
  1634.         {   return;
  1635.         }
  1636.  
  1637.         // walk the files list
  1638.         for (NodePtr = List1.lh_Head; NodePtr->Node.ln_Succ; NodePtr = NodePtr->Node.ln_Succ)
  1639.         {   if (NodePtr->nesting == nesting)
  1640.             {   for (ParentNodePtr = List1.lh_Head; ParentNodePtr->Node.ln_Succ; ParentNodePtr = ParentNodePtr->Node.ln_Succ)
  1641.                 {   if (ParentNodePtr->type == ST_USERDIR && ParentNodePtr->key == NodePtr->parentdir)
  1642.                     {    break;
  1643.                 }   }
  1644.                 ParentNodePtr->unslacksize += NodePtr->unslacksize;
  1645.                 ParentNodePtr->slacksize   += NodePtr->slacksize;
  1646.     }   }   }
  1647.  
  1648.     SetGadgetAttrs
  1649.     (   size_gadgets[GID_8_FG1], MainWindowPtr, NULL,
  1650.         FUELGAUGE_Min,   0,
  1651.         FUELGAUGE_Max,   100,
  1652.         FUELGAUGE_Level, 66,
  1653.         GA_Text,         "Sorting results...",
  1654.         TAG_END
  1655.     );
  1656.  
  1657.     // sort by size
  1658.     while ((List1.lh_Head)->ln_Succ) // while the list is non-empty
  1659.     {   breakval = ra_checkbreak();
  1660.         if (breakval == 2)
  1661.         {   cleanexit(EXIT_SUCCESS);
  1662.         } elif (breakval == 1)
  1663.         {   status = STATUS_STOPPING;
  1664.             SetGadgetAttrs
  1665.             (   size_gadgets[GID_8_FG1], MainWindowPtr, NULL,
  1666.                 GA_Text, "Stopping...",
  1667.                 TAG_END
  1668.             );
  1669.         }
  1670.         if (status == STATUS_STOPPING)
  1671.         {   return;
  1672.         }
  1673.  
  1674.         // walk through the list to determine the largest entry
  1675.         largestsize = 0;
  1676.         if (size.slack)
  1677.         {   for (NodePtr = List1.lh_Head; NodePtr->Node.ln_Succ; NodePtr = NodePtr->Node.ln_Succ)
  1678.             {   if (NodePtr->slacksize >= largestsize)
  1679.                 {   largestsize = NodePtr->slacksize;
  1680.                     largestkey  = NodePtr->key;
  1681.         }   }   }
  1682.         else
  1683.         {   for (NodePtr = List1.lh_Head; NodePtr->Node.ln_Succ; NodePtr = NodePtr->Node.ln_Succ)
  1684.             {   if (NodePtr->unslacksize >= largestsize)
  1685.                 {   largestsize = NodePtr->unslacksize;
  1686.                     largestkey  = NodePtr->key;
  1687.         }   }   }
  1688.  
  1689.         // walk through the list and remove the largest entry
  1690.         for (NodePtr = List1.lh_Head; NodePtr->Node.ln_Succ; NodePtr = NodePtr->Node.ln_Succ)
  1691.         {   if (NodePtr->key == largestkey)
  1692.             {   Remove((struct Node *) NodePtr);
  1693.                 AddTail(&List2, (struct Node *) NodePtr);
  1694.                 break;
  1695.     }   }   }
  1696.  
  1697.     print_list(FALSE);
  1698. }
  1699.  
  1700.